package grit

import (
	"context"
	"fmt"
	"net"
	"os"
	"os/signal"
	"syscall"
	"time"

	//	pb "github.com/segeln/grit/example/protoc"
	"gitee.com/segeln/grit/conf"
	"gitee.com/segeln/grit/log"
	"gitee.com/segeln/grit/registry"

	"gitee.com/segeln/grit/registry/healthcheck"
	"gitee.com/segeln/grit/toolkit/addr"
	"google.golang.org/grpc"
	"google.golang.org/grpc/health/grpc_health_v1"
)

type service struct {
	Ser          *grpc.Server
	opts         *conf.Config
	Registry     registry.Registry
	signRegistry chan int
}

func (obj *service) Interceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
	//健康检查调用不记录日志
	if info.FullMethod != `/grpc.health.v1.Health/Check` {
		log.Infoln("Method.grit:", info.FullMethod, ",req:", req)
	}
	if obj.opts.FunInterceptor != nil {
		return obj.opts.FunInterceptor(ctx, req, info, handler)
	} else {
		return handler(ctx, req)
	}
}

func (obj *service) Init(opts ...conf.SetConfigItem) {
	//obj.opts = newOptions()
}

func (this *service) Run() error {
	ip, err := addr.ExtractIP()
	if err != nil {
		log.Exitln("获取IP失败")
		return err
	}
	log.Init(this.opts.Name, ip, this.opts.Port)
	listen, err := net.Listen("tcp", fmt.Sprintf(":%d", this.opts.Port))
	if err != nil {
		log.Exitln("listen ", this.opts.Port, " failed,error:", err.Error())
		return err
	}
	//注册中心注册服务
	serinfo := &registry.ServiceInfo{}
	serinfo.Address = ip
	serinfo.Port = this.opts.Port
	serinfo.Name = this.opts.Name       // "sergggg"
	serinfo.ID = this.opts.Sid          //.ServiceID //   "id12"
	serinfo.Version = this.opts.Version //  "v1.1"
	//	this.opts.Registry.Init(serinfo)
	//	this.opts.Registry.Register()
	this.Registry.Init(serinfo)
	this.Registry.Register()
	//this.Registry.Selector(serinfo.Name)
	//grpc consul健康检查
	grpc_health_v1.RegisterHealthServer(this.Ser, &healthcheck.HealthImpl{})
	this.signRegistry = make(chan int)
	go this.serRegister(this.signRegistry)
	go this.signalHandle()
	log.Infoln("GRPC Service Name :", this.opts.Name)
	log.Infoln("GRPC Service Name :", this.Registry.GetSid()) // fmt.Sprintf("%s_%s", this.opts.Name, this.opts.Sid))
	log.Infoln("GRPC Service port:", this.opts.Port)

	err = this.Ser.Serve(listen)
	//err := server.ListenAndServe()
	if err != nil {
		log.Errorln("eerrrr:", err.Error())
	}
	//log.Fatal("Server exited")
	fmt.Println("go run.................")

	return nil
}

func (this *service) Server() *grpc.Server {
	return this.Ser
}
func (this *service) Register() registry.Registry {
	return this.Registry
}

//服务注册
func (this *service) serRegister(exit chan int) {
	t := time.NewTicker(time.Duration(this.opts.RegistryCfg.Interval) * time.Second)
	for {
		select {
		case <-t.C:
			//err := s.opts.Server.ServiceRegister()
			err := this.Registry.Register()
			if err != nil {
				log.Warningln("service run Server.Register error: ", err)
			}
		case sign := <-exit:
			t.Stop()
			if sign == 2 {
				this.Close()
			}
			return
		}
	}
}

func (this *service) signalHandle() {
	for {
		ch := make(chan os.Signal)
		signal.Notify(ch, syscall.SIGINT, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGHUP)
		sig := <-ch
		//log.Errorln("Signal received:  ", sig)
		//interrupt
		switch sig {
		// 2 信号量
		case syscall.SIGINT:
			log.Errorln("get SIGINT\n")
			this.signRegistry <- 2
		default:
			log.Errorln("Receive Signal :", sig)
		}
	}
}
func (this *service) Close() {
	log.Infoln("Close.................")
	//删除注册信息
	this.Registry.Deregister()
	//服务清空。。。。。。。。
	//。。。。。。。
	log.Flush()
	os.Exit(1)
}
